/*
 * @Author: Jiraiya
 * @Date: 2020-05-22 19:03:13
 * @LastEditors: Jiraiya
 * @LastEditTime: 2020-05-22 19:18:44
 * @Description: 
 */


/**
 * @description: 5
 * @param {type} 
 * @return: 
 */
export function createFiberRoot(
    containerInfo: any,
    isConcurrent: boolean,
    hydrate: boolean,
): FiberRoot {
    // Cyclic construction. This cheats the type system right now because
    // stateNode is any.
    const uninitializedFiber = createHostRootFiber(isConcurrent);

    let root;
    if (enableSchedulerTracing) {
        root = ({
            current: uninitializedFiber, //root节点对应的Fiber
            containerInfo: containerInfo, //容器元素
            pendingChildren: null, //持久化更新

            //任务调度记录时间
            earliestPendingTime: NoWork,
            latestPendingTime: NoWork,
            earliestSuspendedTime: NoWork,
            latestSuspendedTime: NoWork,
            latestPingedTime: NoWork,

            didError: false, //标记渲染过程的错误

            pendingCommitExpirationTime: NoWork,
            finishedWork: null, //记录一次更新已经完成的任务
            timeoutHandle: noTimeout, // 
            context: null, //主动调用这个的上下文
            pendingContext: null,
            hydrate, //是否调和
            nextExpirationTimeToWorkOn: NoWork, // 本次更新
            expirationTime: NoWork,
            firstBatch: null,
            nextScheduledRoot: null,

            interactionThreadID: unstable_getThreadID(),
            memoizedInteractions: new Set(),
            pendingInteractionMap: new Map(),
        }: FiberRoot);
    } else {
        root = ({
            current: uninitializedFiber,
            containerInfo: containerInfo,
            pendingChildren: null,

            earliestPendingTime: NoWork,
            latestPendingTime: NoWork,
            earliestSuspendedTime: NoWork,
            latestSuspendedTime: NoWork,
            latestPingedTime: NoWork,

            didError: false,

            pendingCommitExpirationTime: NoWork,
            finishedWork: null,
            timeoutHandle: noTimeout,
            context: null,
            pendingContext: null,
            hydrate,
            nextExpirationTimeToWorkOn: NoWork,
            expirationTime: NoWork,
            firstBatch: null,
            nextScheduledRoot: null,
        }: BaseFiberRootProperties);
    }

    uninitializedFiber.stateNode = root;

    // The reason for the way the Flow types are structured in this file,
    // Is to avoid needing :any casts everywhere interaction tracing fields are used.
    // Unfortunately that requires an :any cast for non-interaction tracing capable builds.
    // $FlowFixMe Remove this :any cast and replace it with something better.
    return ((root: any): FiberRoot);
}

/**
 * @description: 6
 * @param {type} 
 * @return: 
 */
function unbatchedUpdates(fn) {
    if (isBatchingUpdates && !isUnbatchingUpdates) {
        isUnbatchingUpdates = true;
        try {
            return fn(a);
        } finally {
            isUnbatchingUpdates = false;
        }
    }
    return fn(a);
}


/**
 * @description: 8
 * @param {type} 
 * @return: 
 */
function updateContainer(
    element,
    container,
    parentComponent,
    callback,
) {
    const current = container.current;
    const currentTime = requestCurrentTime();
    const expirationTime = computeExpirationForFiber(currentTime, current);
    return updateContainerAtExpirationTime( //9
        element,
        container,
        parentComponent,
        expirationTime,
        callback,
    );
}



/**
 * @description: 9
 * @param {type} 
 * @return: 
 */
function updateContainerAtExpirationTime(
    element,
    container,
    parentComponent,
    expirationTime,
    callback,
) {
    // TODO: If this is a nested container, this won't be the root.
    const current = container.current;

    const context = getContextForSubtree(parentComponent);
    if (container.context === null) {
        container.context = context;
    } else {
        container.pendingContext = context;
    }

    return scheduleRootUpdate(current, element, expirationTime, callback);
}